/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2009，所有权利保留。
 * 
 * 项目名：	rumba-web
 * 文件名：	RToolbar.java
 * 模块说明：	
 * 修改历史：
 * Jan 9, 2009 - lxm - 创建。
 */
package com.hd123.rumba.gwt.widget2.client.toolbar;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Widget;

/**
 * 符合Rumba标准的工具条
 * 
 * @author lxm
 * 
 */
public class RToolbar extends Composite {

  private static final String STYLENAME_DEFAULT = "rb-Toolbar";

  /** 工具条对齐方式：左对齐 */
  public static final Alignment ALIGN_LEFT = Alignment.left;
  /** 工具条对齐方式：右对齐 */
  public static final Alignment ALIGN_RIGHT = Alignment.right;

  /** 控件之间的空隙宽度（像素数） */
  private int widgetPadding = 0;

  /**
   * 创建对象实例。
   */
  public RToolbar() {
    super();
    drawSelf();
  }

  /**
   * 清除所有已经被加入的项目，回复到初始状态。
   */
  public void clear() {
    leftItems.clear();
    rightItems.clear();

    int cellCnt = table.getCellCount(0);
    if (cellCnt > 1)
      table.removeCells(0, 1, cellCnt - 1);
    resetFill(0);
  }

  /**
   * 添加一个新的项目，左对齐。
   * 
   * @param item
   *          指定被添加的项目。传入null或已经存在的项目则忽略。
   */
  public void add(Widget item) {
    add(item, Alignment.left);
  }

  /**
   * 添加一个新的项目。
   * 
   * @param item
   *          指定被添加的项目。传入null或已经存在的项目则忽略。
   * @param align
   *          指定对齐方式，null表示左对齐。
   */
  public void add(Widget item, Alignment align) {
    if (item == null)
      return;
    if (contains(item))
      return;
    if (align == null)
      align = Alignment.left;

    if (Alignment.left.equals(align))
      addToLeft(item);
    else
      addToRight(item);
  }

  /**
   * 插入指定的项目。
   * 
   * @param newItem
   *          指定被添加的项目。传入null或已经存在的项目则忽略。
   * @param nextItem
   *          将被添加的项目插入到指定项目前。传入null或不存在的项目则等价于
   *          {@link #add(Widget)}。
   */
  public void insert(Widget newItem, Widget nextItem) {
    if (newItem == null)
      return;
    if (contains(newItem))
      return;
    if (nextItem == null && !contains(nextItem))
      return;

    if (leftItems.contains(nextItem))
      insertToLeft(newItem, nextItem);
    else if (rightItems.contains(nextItem))
      insertToRight(newItem, nextItem);
    else
      throw new RuntimeException("指定的参数nextItem必须是已经存在的项目。");
  }

  /**
   * 删除指定的项目。
   * 
   * @param item
   *          指定被删除的项目，若传入的项目不存在则不作任何事。
   */
  public void remove(Widget item) {
    if (leftItems.contains(item))
      removeFromLeft(item);
    else if (rightItems.contains(item))
      removeFromRight(item);
  }

  /**
   * 判断是否已经包含了指定的项目。
   * 
   * @param item
   *          指定的项目。
   * @return
   */
  public boolean contains(Widget item) {
    return leftItems.contains(item) && rightItems.contains(item);
  }

  /**
   * 控件之间的空隙宽度（像素数），默认为0。
   * 
   * @return
   */
  public int getWidgetPadding() {
    return widgetPadding;
  }

  /**
   * 设置控件之间的空隙宽度（像素数），默认为0。
   * 
   * @param widgetPadding
   */
  public void setWidgetPadding(int widgetPadding) {
    if (this.widgetPadding == widgetPadding)
      return;

    this.widgetPadding = widgetPadding;
    for (int col = 0; col < table.getCellCount(0); col++) {
      if (table.getWidget(0, col) == null)
        continue;
      DOM.setStyleAttribute(table.getCellFormatter().getElement(0, col), "paddingRight",
          widgetPadding + "px");
    }
  }

  /** 作为容器。[pnlOutter/] */
  private FlexTable table;
  /** 所有左对齐的项目列表 List of Widget */
  private List leftItems = new ArrayList();
  /** 所有右对齐的项目列表 List of Widget */
  private List rightItems = new ArrayList();

  private void drawSelf() {
    table = new FlexTable();
    table.setWidth("100%");
    table.setCellSpacing(0);
    table.setCellPadding(0);
    resetFill(0);
    initWidget(table);
    setStyleName(STYLENAME_DEFAULT);
  }

  private void addToLeft(Widget item) {
    assert item != null;
    leftItems.add(item);

    int column = leftItems.size() - 1;
    resetItem(column, item);
    column++;
    resetFill(column);
    column++;
    for (int i = 0, n = rightItems.size(); i < n; i++) {
      Widget item2 = (Widget) rightItems.get(i);
      resetItem(column, item2);
      column++;
    }
  }

  private void addToRight(Widget item) {
    assert item != null;
    rightItems.add(item);

    int column = table.getCellCount(0);
    resetItem(column, item);
  }

  private void insertToLeft(Widget newItem, Widget nextItem) {
    assert newItem != null;
    assert nextItem != null;

    int index = leftItems.indexOf(nextItem);
    assert index >= 0;
    leftItems.add(index, newItem);

    int column = index;
    resetItem(column, newItem);
    column++;
    while (column < leftItems.size()) {
      Widget item = (Widget) leftItems.get(column);
      resetItem(column, item);
      column++;
    }
    resetFill(column);
    column++;
    for (int i = 0, n = rightItems.size(); i < n; i++) {
      Widget item = (Widget) rightItems.get(i);
      resetItem(column, item);
      column++;
    }
  }

  private void insertToRight(Widget newItem, Widget nextItem) {
    assert newItem != null;
    assert nextItem != null;

    int index = rightItems.indexOf(nextItem);
    assert index >= 0;
    rightItems.add(index, newItem);

    int column = leftItems.size() + 1 + index;
    while (index < rightItems.size()) {
      Widget item = (Widget) rightItems.get(index);
      resetItem(column, item);
      column++;
      index++;
    }
  }

  private void removeFromLeft(Widget item) {
    assert item != null;

    int index = leftItems.indexOf(item);
    assert index >= 0;
    leftItems.remove(item);

    int column = index;
    while (column < leftItems.size()) {
      Widget item2 = (Widget) leftItems.get(column);
      resetItem(column, item2);
      column++;
    }
    resetFill(column);
    column++;
    for (int i = 0, n = rightItems.size(); i < n; i++) {
      Widget item2 = (Widget) rightItems.get(i);
      resetItem(column, item2);
      column++;
    }

    table.removeCell(0, table.getCellCount(0));
  }

  private void removeFromRight(Widget item) {
    assert item != null;

    int index = rightItems.indexOf(item);
    assert index >= 0;
    rightItems.remove(item);

    int column = leftItems.size() + 1 + index;
    while (index < rightItems.size()) {
      Widget item2 = (Widget) rightItems.get(index);
      resetItem(column, item2);
      column++;
      index++;
    }

    table.removeCell(0, table.getCellCount(0));
  }

  private void resetFill(int column) {
    table.getCellFormatter().setWidth(0, column, "100%");
    table.getCellFormatter().setWordWrap(0, column, false);
  }

  private void resetItem(int column, Widget item) {
    table.setWidget(0, column, item);
    table.getCellFormatter().setWidth(0, column, "");
    table.getCellFormatter().setWordWrap(0, column, false);
    DOM.setStyleAttribute(table.getCellFormatter().getElement(0, column), "paddingRight",
        widgetPadding + "px");
  }

  /**
   * 工具条对齐方式。
   * 
   * @author lxm
   * 
   */
  public static class Alignment {

    /** 左对齐 */
    public static final Alignment left = new Alignment(-1);
    /** 右对齐 */
    public static final Alignment right = new Alignment(1);

    private Alignment(int value) {
      super();
      this.value = value;
    }

    private int value;

    public boolean equals(Object a) {
      if (a instanceof Alignment)
        return ((Alignment) a).value == value;
      return false;
    }
  }
}
